﻿using Architecture.CrossCutting.Common.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http.Routing;

namespace Architecture.CrossCutting.Web.Tracing.Model
{
    public class WebApiLog : BaseLog
    {

        public enum RequestStep
        {
            BeforeCall = 0,
            AfterCall = 1
        }

        public string Application { get; set; }
        public string User { get; set; }
        public RequestStep Step { get; set; }

        public string RequestIpAddress { get; set; }
        public string RequestContentType { get; set; }
        //public string RequestContentBody { get; set; }
        public string RequestUri { get; set; }
        public string RequestMethod { get; set; }
        public string RequestRouteTemplate { get; set; }
        public string RequestRouteData { get; set; }
        public string RequestHeaders { get; set; }
        public DateTime? RequestSended { get; set; }
        public string ResponseContentType { get; set; }
        //public string ResponseContentBody { get; set; }
        public int? ResponseStatusCode { get; set; }
        public string ResponseHeaders { get; set; }
        public DateTime? ResponseReceived { get; set; }

        public Int64 RequestDuration { get; set; }

        private Int64 RequestSendedTicks { get; set; }
        private Int64 ResponseReceivedTicks { get; set; }


        public WebApiLog() : base()
        { }

        public void RegisterRequest(HttpRequestMessage request)
        {

            if (request.Properties.ContainsKey("MS_HttpContext"))
            {
                var context = ((HttpContextBase)request.Properties["MS_HttpContext"]);
                this.User = String.IsNullOrEmpty(context.User.Identity.Name) ? "Anonymous" : context.User.Identity.Name;
                this.RequestContentType = context.Request.ContentType;
                this.RequestIpAddress = context.Request.UserHostAddress;

            }

            var routeData = request.GetRouteData();
            if (routeData != null)
            {
                this.RequestRouteTemplate = routeData.Route.RouteTemplate;
                this.RequestRouteData = SerializeRouteData(routeData);
            }

            this.Step = RequestStep.BeforeCall;
            this.RequestMethod = request.Method.Method;
            this.RequestHeaders = SerializeHeaders(request.Headers);
            this.RequestUri = request.RequestUri.ToString();

        }

        public void RegisterResponse(HttpResponseMessage response)
        {
            this.Step = RequestStep.AfterCall;
            this.ResponseStatusCode = (int)response.StatusCode;

            if (response.Content != null)
            {
                //this.ResponseContentBody = response.Content.ReadAsStringAsync().Result;
                this.ResponseContentType = response.Content.Headers.ContentType.MediaType;
                this.ResponseHeaders = SerializeHeaders(response.Content.Headers);
            }

        }


        public void SetStartRequestSent()
        {
            this.RequestSendedTicks = Environment.TickCount;
            this.RequestSended = DateTime.UtcNow;
        }

        public void SetResponseReceived(Int64 requestDuration)
        {
            this.ResponseReceivedTicks = Environment.TickCount;
            this.ResponseReceived = DateTime.UtcNow;
            this.RequestDuration = requestDuration;
        }

        private string SerializeHeaders(HttpHeaders headers)
        {
            var dict = new Dictionary<string, string>();


            foreach (var item in headers.ToList())
            {
                if (item.Value != null)
                {
                    var header = String.Empty;
                    foreach (var value in item.Value)
                    {
                        header += value + " ";
                    }


                    // Trim the trailing space and add item to the dictionary 
                    header = header.TrimEnd(" ".ToCharArray());
                    dict.Add(item.Key, header);
                }
            }


            return JsonConvert.SerializeObject(dict, Formatting.Indented);
        }

        private string SerializeRouteData(IHttpRouteData routeData)
        {
            return JsonConvert.SerializeObject(routeData.Values, Formatting.Indented);
        }

    }
}
